#pragma once
#include"util.hpp"
#include "index.hpp"
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <jsoncpp/json/json.h>
#include "log.hpp"
namespace Util_Searcher{
    class Searcher{
        private:
        Index::index*index_root;
        public:
        Searcher(){};
        ~Searcher(){};

        //初始化数据和搜索引擎
        void Init_Searcher(const std::string&input)
        {
            //获取单例==>创建index对象
            index_root=Index::index::Get_Singleton();
            //Debug
            // std::cout<<"创建Index单例成功 !"<<std::endl;
            LOG(NORMAL,"创建Index单例成功 !");
            //建立索引
            index_root->BuildIndex(input);
            //Debug
            // std::cout<<"索引全部建立成功 !"<<std::endl;
            LOG(NORMAL,"索引全部建立成功 !");
        }
        //编写搜索模块
        void Searcher_In_Out(const std::string&User_worlds,std::string*output)
        {
            Index::Forback Forbacklist_all; //用来存储用户所有的搜索词对应的倒排
            std::vector<std::string>Divide_worlds;  //存储划分好的用户关键字
            util::JiebaUtil::CutString(User_worlds,&Divide_worlds);
            for(auto&item:Divide_worlds)
            {
                //因为我们是按照小写进行索引建立的，所以我们需要把用户的搜索词也要转为小写
                boost::to_lower(item);
                Index::Forback*tmp_list=index_root->GetForbackInfo(item);   //根据关键字找到对应的倒排
                if(tmp_list==nullptr)   continue;
                Forbacklist_all.insert(Forbacklist_all.end(),tmp_list->begin(),tmp_list->end()); //插入总的倒排数组中
            }
            //按照权重进行排序
            std::sort(Forbacklist_all.begin(),Forbacklist_all.end(),[](Index::Forback_Mounted&l1,Index::Forback_Mounted&l2)
            {
                //进行降序 >
                return l1.weight>l2.weight;
            });
            //对于整个倒排数组进行遍历
            for(auto&e:Forbacklist_all)
            {
                Index::Forward_Mounted *Doc=index_root->GetForwardInfo(e.id);
                if(nullptr==Doc)
                    continue;
                //进行Json序列化
                Json::Value root;
                Json::Value elm;
                elm["title"]=Doc->title;
                elm["content"]=Get_Desc_Doc_Content(e.key_world,Doc->content);
                elm["url"]=Doc->url;
                root.append(elm);
                Json::StyledWriter writer;
                *output=writer.write(root);
            }
        }
        //截取有效的content
        std::string Get_Desc_Doc_Content(const std::string&key_world,const std::string&content)
        {
            //找到key_world在content第一次出现的位置，然后往前找50字符，再往后找100字符，这段区域为有效字符
            const int prev_step=50;//往前
            const int back_step=100;//往后
            //找到首次出现
            auto iter=std::search(key_world.begin(),key_world.end(),content.begin(),content.end(),[](int x,int y){
                return (std::tolower(x)==std::tolower(y));
            });
            if(iter==key_world.end()) return "None1";
            int pose=std::distance(key_world.end(),iter);   //找到第一次出现的位置

            std::size_t start=0;
            std::size_t end=key_world.size()-1;
            //往前走50
            if(pose>start+prev_step) start=pose-prev_step;
            //往后走100
            if(pose<end-back_step) end=pose+back_step;
            //虽然触发的可能性小，但是为了起个保障
            if(start>end)   return "None2";
            //按照start和end进行截取字符串
            std::string ret_string =key_world.substr(start,end-start);
            return ret_string+="……";
        }
    };
}